#ifndef BOTTOMWIDGET_H
#define BOTTOMWIDGET_H

#include <QWidget>
#include <QPushButton>
#include <QPainter>
#include <QTimer>
#include <QTime>
#include <QPainterPath>
#include <QPropertyAnimation>
#include <QPixmap>
#include <QSlider>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QMediaPlayer>
#include <QMediaMetaData>
#include <QAudioOutput>
#include <QUrl>
#include <clickedlabel.h>

class RotatingButton : public QPushButton
{
    Q_OBJECT
    Q_PROPERTY(int rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
public:
    explicit RotatingButton(QWidget *parent = nullptr)
        : QPushButton(parent)//, angle(0)
    {
        setFixedSize(70, 70);
        setStyleSheet("border:none");
        animation = new QPropertyAnimation(this, "rotation", this);
        animation->setDuration(30000);
        animation->setStartValue(0);
        animation->setEndValue(360);
        animation->setLoopCount(-1);
        animation->setEasingCurve(QEasingCurve::Linear);
    }

    int rotation() const
    {
        return angle;
    }
    void SetPixmap(const QString&filepath)
    {
        QImage image(filepath);
        pixmap=QPixmap::fromImage(image);
        pixmap.setDevicePixelRatio(this->devicePixelRatio());
        if(pixmap.load(filepath))
            pixmap=pixmap.scaled(size(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
        else
        {
            qDebug()<<"BottomWidget: pixmap load is failed";;
        }
    }
    void SetPixmap(const QByteArray&data)
    {
        QImage image(data);
        pixmap=QPixmap::fromImage(image);
        pixmap.setDevicePixelRatio(this->devicePixelRatio());
        if(pixmap.loadFromData(data))
            pixmap=pixmap.scaled(size(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
        else
        {
            qDebug()<<"BottomWidget: pixmap load is failed";;
        }
    }
    void SetImage(const QImage& image)
    {
        pixmap=QPixmap::fromImage(image);
        pixmap=pixmap.scaled(size(), Qt::KeepAspectRatioByExpanding,Qt::SmoothTransformation);
    }
signals:
    void rotationChanged(qint16 angle);
public slots:
    void start()
    {
        animation->start();
    }
    void pause()
    {
        animation->pause();
    }
protected slots:
    void setRotation(int a)
    {
        angle = a;
        update();
        emit rotationChanged(angle);
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {

        QPushButton::paintEvent(event);

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.translate(width() / 2, height() / 2);
        painter.rotate(angle);
        painter.translate(-width() / 2, -height() / 2);
        painter.setPen(QPen(Qt::black,10));
        painter.drawEllipse(rect().center(),25,25);
        // 绘制旋转的图片
        QPainterPath path;
        path.addEllipse(rect().center(),25,25);
        painter.setClipPath(path);
        painter.drawPixmap(rect(),pixmap);
    }

private slots:


private:
    QPropertyAnimation*animation;
    int angle;  // 当前旋转角度
    QPixmap pixmap;
};

class Slider:public QSlider
{
    Q_OBJECT
public:
    Slider(QWidget*parent=nullptr):QSlider(parent)
    {
        setTracking(false);
        setStyleSheet(
            "QSlider::groove:vertical {"
            "width: 4px;"
            "background: #e4e8ec;"
            "}"
            "QSlider::handle:vertical {"
            "background: #ffffff;"
            "border: 1px solid #5c5c5c;"
            "height: 10px;"
            "margin: -4px;"
            "border-radius: 5px;"
            "}"
            "QSlider::add-page:vertical {"
            "background: #ea3e3e;"
            "}"
            "QSlider::groove:horizontal {"
            "height: 4px;"
            "background: #e4e8ec;"
            "}"
            "QSlider::handle:horizontal {"
            "background: #ffffff;"
            "border: 1px solid #5c5c5c;"
            "width: 10px;"
            "margin: -4px;"
            "border-radius: 5px;"
            "}"
            "QSlider::sub-page:horizontal {"
            "background: #ea3e3e;"
            "}"
            );

        setOrientation(Qt::Horizontal);
    }
signals:
    void sliderValueChanged(qint32 value);

protected:
    void mousePressEvent(QMouseEvent*e)override
    {
        QSlider::mousePressEvent(e);
        double per;
        if(this->orientation()==Qt::Vertical)
            per=(height()-e->pos().y())*1.0/height();
        else
            per=(e->pos().x()*1.0)/width();
        int value=(maximum()-minimum())*per;
        setValue(value);
    }
    void mouseReleaseEvent(QMouseEvent*e)override
    {
        QSlider::mouseReleaseEvent(e);
        emit sliderValueChanged(value());
    }
    void keyPressEvent(QKeyEvent*e)override
    {
        if(e->key()==Qt::Key_Up||e->key()==Qt::Key_Right)
        {
            setValue(value()+1);
            emit sliderValueChanged(value());
        }
        else if(e->key()==Qt::Key_Down||e->key()==Qt::Key_Left)
        {
            setValue(value()-1);
            emit sliderValueChanged(value());
        }
    }

private:
};

class MusicSliderWidget:public QWidget
{
    Q_OBJECT
public:
    MusicSliderWidget(QWidget*parent=nullptr):QWidget(parent)
    {
        hlayout1=new QHBoxLayout;
        hlayout2=new QHBoxLayout;
        vlayout=new QVBoxLayout(this);
        playlabel=new QLabel;
        timelabel=new QLabel;
        slider=new Slider;
        likebtn=new QPushButton;
        lastbtn=new QPushButton;
        nextbtn=new QPushButton;
        playbtn=new QPushButton;
        modebtn=new QPushButton;

        likebtn->setIcon(QIcon(":/icon/normal.png"));
        setBtnStyleSheet(likebtn);
        lastbtn->setIcon(QIcon(":/icon/last.png"));
        setBtnStyleSheet(lastbtn);
        lastbtn->setIconSize(QSize(30,30));
        playbtn->setIcon(QIcon(":/icon/play.png"));
        setBtnStyleSheet(playbtn);
        playbtn->setIconSize(QSize(32,32));
        nextbtn->setIcon(QIcon(":/icon/next.png"));
        setBtnStyleSheet(nextbtn);
        nextbtn->setIconSize(QSize(30,30));
        modebtn->setIcon(QIcon(":/icon/list.png"));
        setBtnStyleSheet(modebtn);

        playlabel->setText("00:00");
        timelabel->setText("00:00");

        slider->setOrientation(Qt::Horizontal);

        hlayout1->addStretch(1);
        hlayout1->addWidget(likebtn);
        hlayout1->addWidget(lastbtn);
        hlayout1->addWidget(playbtn);
        hlayout1->addWidget(nextbtn);
        hlayout1->addWidget(modebtn);
        hlayout1->addStretch(1);
        hlayout2->addWidget(playlabel);
        hlayout2->addWidget(slider);
        hlayout2->addWidget(timelabel);
        vlayout->addLayout(hlayout1);
        vlayout->addLayout(hlayout2);

        connect(slider,&Slider::sliderValueChanged,this,&MusicSliderWidget::onSliderValueChange);
        connect(likebtn,&QPushButton::clicked,this,&MusicSliderWidget::onClickLikeButton);
        connect(lastbtn,&QPushButton::clicked,this,[this]{emit clickLast();});
        connect(playbtn,&QPushButton::clicked,this,&MusicSliderWidget::onClickPlayButton);
        connect(nextbtn,&QPushButton::clicked,this,[this]{emit clickNext();});
        connect(modebtn,&QPushButton::clicked,this,[this]{mode=(mode+1)%4;emit clickMode(mode);});

        setFixedSize(500,75);
    }
    void SetTime(int h,int m,int s)
    {
        songtime.setHMS(h,m,s);
        playtime.setHMS(0,0,0);
        timelabel->setText(songtime.toString("mm:ss"));
        playlabel->setText(playtime.toString("mm:ss"));
        //slider的设置
        slider->setValue(0);
        slider->setRange(0,h*3600+m*60+s);
    }
    void SetTime(qint32 time)
    {
        songtime.setHMS(time/3600,(time%3600)/60,time%60);
        playtime.setHMS(0,0,0);
        timelabel->setText(songtime.toString("mm:ss"));
        playlabel->setText(playtime.toString("mm:ss"));
        //slider的设置
        slider->setValue(0);
        slider->setRange(0,time);
    }
    void SetLike(){likebtn->setIcon(QIcon(":/icon/like.png"));islike=true;}
    void SetNormal(){likebtn->setIcon(QIcon(":/icon/normal.png"));islike=false;}
    void SetPlayTime(qint32 time)
    {
        slider->setValue(time);
        playtime.setHMS(time/3600,(time%3600)/60,time%60);
        playlabel->setText(playtime.toString("mm:ss"));
    }
signals:
    void clickPlay(qint32 time);
    void clickPause();
    void clickLike();
    void clickNormal();
    void clickNext();
    void clickLast();
    void clickMode(qint16);

public slots:
    void play(int h,int m,int s)
    {
        playtime.setHMS(h,m,s);
        playlabel->setText(playtime.toString("mm:ss"));
        slider->setValue(h*3600+m*60+s);
        isplay=true;
        playbtn->setIcon(QIcon(":/icon/pause.png"));
    }
    void play(qint32 time)
    {
        playtime.setHMS(time/3600,(time%3600)/60,time%60);
        playlabel->setText(playtime.toString("mm:ss"));
        slider->setValue(time);
        isplay=true;
        playbtn->setIcon(QIcon(":/icon/pause.png"));
    }
    void pause()
    {
        isplay=false;
        playbtn->setIcon(QIcon(":/icon/play.png"));
    }
private slots:
    void onSliderValueChange(qint32 value)
    {
        playtime.setHMS(value/3600,(value%3600)/60,value%60);
        playlabel->setText(playtime.toString("mm:ss"));
        play(value);
        emit clickPlay(value);
    }
    void onClickPlayButton()
    {
        if(!isplay)
        {
            play(slider->value());
            qint32 value=playtime.hour()*3600+playtime.minute()*60+playtime.second();
            emit clickPlay(value);
        }
        else
        {
            pause();
            emit clickPause();
        }
    }
    void onClickLikeButton()
    {
        if(islike)
        {
            SetNormal();
            emit clickNormal();
        }
        else
        {
            SetLike();
            emit clickLike();
        }
    }
private:
    void setBtnStyleSheet(QPushButton*btn)
    {
        btn->setStyleSheet("QPushButton{border:none;background:transparent;}");
        btn->setIconSize(QSize(25,25));
    }
    bool isplay=false;
    bool islike=false;
    qint16 mode=0;
    QHBoxLayout*hlayout1,*hlayout2;
    QVBoxLayout*vlayout;
    QLabel*playlabel,*timelabel;
    Slider*slider;
    QPushButton*likebtn,*lastbtn,*nextbtn,*playbtn,*modebtn;
    QTime playtime{},songtime{};

};

class VolumeWidget:public QWidget
{
    Q_OBJECT
public:
    VolumeWidget(QWidget*parent=nullptr):QWidget(parent){
        s=new Slider;
        label=new QLabel;
        vlayout=new QVBoxLayout(this);
        hlayout1=new QHBoxLayout;
        hlayout2=new QHBoxLayout;

        s->setTracking(true);
        s->setRange(0,100);
        s->setOrientation(Qt::Vertical);
        label->setText(QString::number(s->value())+"%");
        label->setAlignment(Qt::AlignCenter);
        label->setFixedSize(40,25);

        hlayout1->addStretch(1);
        hlayout1->addWidget(s);
        hlayout1->addStretch(1);
        hlayout2->addStretch(1);
        hlayout2->addWidget(label);
        hlayout2->addStretch(1);
        vlayout->addLayout(hlayout1);
        vlayout->addLayout(hlayout2);

        setWindowFlags(Qt::Tool|Qt::FramelessWindowHint);
        setFixedSize(60,180);
        connect(s,&Slider::sliderValueChanged,this,&VolumeWidget::onSliderValueChanged);
    }
    void SetVolume(qint32 vol){s->setValue(vol);label->setText(QString::number(vol)+'%');}

signals:
    void volumeChange(qint32);
protected:
    void paintEvent(QPaintEvent*e)override
    {
        Q_UNUSED(e)
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(QColor("#ffffff"));
        painter.setPen(Qt::NoPen);
        painter.drawRoundedRect(rect(),10,10);
    }
private:
    void onSliderValueChanged(qint32 value)
    {
        label->setText(QString::number(value)+"%");
        emit volumeChange(value);
    }
    Slider*s;
    QLabel*label;
    QHBoxLayout*hlayout1,*hlayout2;
    QVBoxLayout*vlayout;
};

class MultiLabel:public ClickedLabel
{
    Q_OBJECT
public:
    MultiLabel(QWidget *parent=nullptr):ClickedLabel(parent){}
    void SetStringList(const QStringList&strlist)
    {
        if(strlist.isEmpty())
            return;
        QString str;
        //应对QMediaMetaData::ContributingArtist中全在一个QStringList的情况
        if(strlist.first().contains('/'))
        {
            str=strlist.first();
            mstrlist=str.split('/',Qt::SkipEmptyParts);
        }
        //应对不在一个QStringList的情况
        else
        {
            mstrlist=strlist;
            for(const auto&elem:strlist)
            {
                str+=elem+'/';
            }
            str.erase(str.end()-1,str.end());
        }
        setText(str);
    }

protected:
    void mousePressEvent(QMouseEvent*e)override
    {
        QLabel::mousePressEvent(e);
        qDebug()<<FindString(e->position());
        emit clicked(FindString(e->position()));
    }
private:
    QString FindString(const QPointF&pointf)
    {
        double width=pointf.x();
        QFontMetrics fm(font());
        for(int i=0;i<mstrlist.size();i++)
        {
            QRect rect=fm.boundingRect(mstrlist[i]);
            QRect symbolrect=fm.boundingRect('/');
            if(rect.width()>=width||i==mstrlist.size()-1)
                return mstrlist[i];
            else
                width=width-rect.width()-symbolrect.width();
        }
        return text();//如果都没找到，说明是没有SetStringList()
    }
    QStringList mstrlist;
};

class MovingLabelWidget : public QWidget
{
    Q_OBJECT

public:
    MovingLabelWidget(QWidget *parent = nullptr) : QWidget(parent)
    {
        label1 = new MultiLabel(this);
        label2 = new MultiLabel(this);
        label3=new MultiLabel(this);
        label4=new MultiLabel(this);

        animation1 = new QPropertyAnimation(label1, "geometry");
        animation2 = new QPropertyAnimation(label2, "geometry");
        animation3 = new QPropertyAnimation(label3, "geometry");
        animation4 = new QPropertyAnimation(label4, "geometry");

        animation1->setEasingCurve(QEasingCurve::Linear);
        animation2->setEasingCurve(QEasingCurve::Linear);
        animation3->setEasingCurve(QEasingCurve::Linear);
        animation4->setEasingCurve(QEasingCurve::Linear);

        connect(animation1, &QPropertyAnimation::finished, this,&MovingLabelWidget::onAnimationFinished);
        connect(animation2, &QPropertyAnimation::finished, this,&MovingLabelWidget::onAnimationFinished);
        connect(animation3, &QPropertyAnimation::finished, this,&MovingLabelWidget::onAnimationFinished);
        connect(animation4, &QPropertyAnimation::finished, this,&MovingLabelWidget::onAnimationFinished);
        connect(label1,&MultiLabel::clicked,[this](const QString&str){emit clickLabel(str);});
        connect(label2,&MultiLabel::clicked,[this](const QString&str){qDebug()<<str;emit clickLabel(str);});
        connect(label3,&MultiLabel::clicked,[this](const QString&str){emit clickLabel(str);});
        connect(label4,&MultiLabel::clicked,[this](const QString&str){emit clickLabel(str);});
    }

    void SetSongNameFont(const QFont&font){label1->setFont(font);label3->setFont(font);}
    void SetSongerFont(const QFont&font){label2->setFont(font);label4->setFont(font);}
    void SetSpeed(double s){speed=s;}
    void SetSongInfo(const QString&songname,const QStringList&songers)
    {
        label1->setText(songname);
        label2->SetStringList(songers);
        label3->setText(songname);
        label4->SetStringList(songers);
        label2->setStyleSheet("color:grey");
        label4->setStyleSheet("color:grey");

        QFontMetrics fm1(label1->font());
        QRect textRect1 = fm1.boundingRect(label1->text());
        label1->setFixedSize(textRect1.width()+10 , textRect1.height());
        label3->setFixedSize(textRect1.width()+10 , textRect1.height());
        size1=label1->size();


        QFontMetrics fm2(label2->font());
        QRect textRect2 = fm1.boundingRect(label2->text());
        label2->setFixedSize(textRect2.width()+10 , textRect2.height());
        label4->setFixedSize(textRect2.width()+10 , textRect2.height());
        size2=label2->size();

        animation1->stop();
        animation2->stop();
        animation3->stop();
        animation4->stop();


        animation1->setDuration(size1.width()/speed);
        animation1->setStartValue(QRect(0,0,size1.width(),size1.height()));
        animation1->setEndValue(QRect(-size1.width(),0,size1.width(),size1.height()));

        animation2->setDuration((size1.width()+10+size2.width())/speed);
        animation2->setStartValue(QRect(size1.width()+10,0,size2.width(),size2.height()));
        animation2->setEndValue(QRect(-size2.width(),0,size2.width(),size2.height()));

        animation3->setDuration((2*size1.width()+30+size2.width())/speed);
        animation3->setStartValue(QRect(size1.width()+30+size2.width(),0,size1.width(),size2.height()));
        animation3->setEndValue(QRect(-size1.width(),0,size1.width(),size1.height()));

        animation4->setDuration((2*size1.width()+40+size2.width()*2)/speed);
        animation4->setStartValue(QRect(2*size1.width()+40+size2.width(),0,size2.width(),size2.height()));
        animation4->setEndValue(QRect(-size2.width(),0,size2.width(),size2.height()));

        if(size1.width()+size2.width()>width())
        {
            animation1->start();
            animation2->start();
            animation3->start();
            animation4->start();
        }
        else
        {
            label1->setGeometry(0,0,size1.width(),size1.height());
            label2->setGeometry(size1.width()+10,0,size2.width(),size2.height());
            label3->hide();
            label4->hide();
        }
    }

signals:
    void clickLabel(const QString&);
private slots:
    void onAnimationFinished()
    {
        QPropertyAnimation *animation = qobject_cast<QPropertyAnimation *>(sender());

        if(animation==animation1||animation==animation3)
        {
            animation->setDuration((2*size1.width()+60+size2.width()*2)/speed);
            animation->setStartValue(QRect(size1.width()+60+2*size2.width(),0,size2.width(),size2.height()));
            animation->setEndValue(QRect(-size1.width(),0,size1.width(),size2.height()));
        }
        else
        {
            animation->setDuration((2*size1.width()+60+size2.width()*2)/speed);
            animation->setStartValue(QRect(2*size1.width()+60+size2.width(),0,size2.width(),size2.height()));
            animation->setEndValue(QRect(-size2.width(),0,size2.width(),size2.height()));

        }
        animation->start();

    }

private:
    MultiLabel *label1;
    MultiLabel *label2;
    MultiLabel *label3;
    MultiLabel *label4;
    QPropertyAnimation *animation1;
    QPropertyAnimation *animation2;
    QPropertyAnimation *animation3;
    QPropertyAnimation *animation4;
    QSize size1,size2;
    double speed=0.04;
};

/*
 * class RotatingButton
 * {
 *  void SetPixmap(const QString&filepath)
 *  void SetPixmap(const QByteArray&data)
 *  void start()
 *  void pause()
 * }
*/

/*
 *class MusicSliderWidget
 *{
 *public:
 *  void SetTime(int h,int m,int s)设置音乐的时长
 * signals:
    void clickPlay(qint32);
    void clickPause();
    void clickLike();
    void clickDislike();
    void clickNext();
    void clickLast();
    void clickMode(qint16);
* public slot:
*   void start();
    void pause();
 *}
 *
 */

/*
 *class MovingLabelWidget
 *{
 *  void SetSongNameFont(QFont&font)
    void SetSongerFont(QFont&font)
    void SetSpeed(double s)
    void SetSongInfo(const QString&songname,const QString&songer)
 *}
 *
 */


class BottomWidget : public QWidget
{
    Q_OBJECT
public:
    BottomWidget(QWidget *parent = nullptr);
    ~BottomWidget()
    {
    }

    //MovingLabelWidget
    void SetSongInfo(const QString&songname,const QStringList&songers){movinglabel->SetSongInfo(songname,songers);}
    void SetSpeed(double s){movinglabel->SetSpeed(s);}
    //MusicSliderWidget
    void SetTime(qint32 h,qint32 m,qint32 s){slider->SetTime(h,m,s);}
    void SetLike(bool like){if(like)slider->SetLike();else slider->SetNormal();}
    //RotatingButton
    void SetPixmap(const QString&filepath){rbtn->SetPixmap(filepath);}
    void SetPixmap(const QByteArray&data){rbtn->SetPixmap(data);}
    //other
    void SetVolume(qint32 vol){audiooutput->setVolume(1.0*vol/100);volume->SetVolume(vol);}
    void SetPlayStream(const QUrl&url)
    {
        qDebug()<<"play:"<<url;
        player->setSource(url);
        play(0);
    }

signals:
    void nextSignal();
    void previousSignal();
    void likeSignal(bool flag);
    void endSignal();
    void modeSignal();

    void playModeSignal();
    void favourSignal(bool flag);
    void commentSignal();
    void shareSignal();
    void downloadSignal();
    void lyricsSignal();

    void searchSignal(const QString&);

    void newMainWindowSize(const QSize& size);

public slots:
    void play(qint32 time){rbtn->start();slider->play(time);player->setPosition(time*1000);player->play();}
    void pause(){rbtn->pause();slider->pause();player->pause();}
    void onMainWindowResize(const QSize& size);
    void onPlaySignal(const QUrl&url);
protected:
    void paintEvent(QPaintEvent*e)override;
    void mousePressEvent(QMouseEvent* e) override;
    void mouseReleaseEvent(QMouseEvent* e) override;
    void mouseMoveEvent(QMouseEvent* e) override;
    bool event(QEvent *event) override;

private slots:
    void onPositionChanged(qint64 position);
    void onDurationChanged(qint64 duration);
    void onMediaStatusChanged(QMediaPlayer::MediaStatus status);
    void onMetaDataChanged();
private:

    RotatingButton*rbtn;
    MovingLabelWidget*movinglabel;
    MusicSliderWidget*slider;
    VolumeWidget*volume;

    QHBoxLayout*mainlayout,*hlayout;
    QVBoxLayout*vlayout;
    QVector<QPushButton*>buttons;

    QMediaPlayer*player;
    QAudioOutput*audiooutput;

    bool isdrag=false;
    qint32 time=0;
    qint32 lastposition=-1;
    QPoint startpoint;
};


#endif // BOTTOMWIDGET_H
